#include "utlity.h"
#include <list> 
#include <Magick++.h> 
#include <wx/msgdlg.h> 
#include <wx/image.h>
#include <wx/filename.h>
using namespace std; 
using namespace Magick;

struct SNameRowColumn
{
	char name[32];
	int c,r;
};

SNameRowColumn NAME_ROW_COLUMN[] = {
	"_qj",11,2,
	"_sw",11,2,
	"_sy",4,2,
	"_sf",9,2,
	"_fd",6,5,
	"_pb",8,5,
	"_kz",7,2,
	"_cc",1,2,
	"_bj",5,2,
	"_fy",1,2,
	"_fh",10,2,
	"_zd",9,2,
	"_pk",9,2,
	"_sf",9,2,
	"_bc",9,2,
	"_zh",13,2,
	"_sw",11,2,
	"_fd2",6,5,
	"_zh2",13,2,
	"_bj2",5,2,
	"_pb2",8,5
};

SNameRowColumn MONSTER_ROW_COLUMN[] = {
	"_bj",6,2,
	"_gj",5,2,
	"_fy",1,2,
	"_pb",6,5,
	"_sf",3,2,
	"_sw",9,2,
	"_zd",6,5,
};

bool GetRowCol(wxString &name,int &row,int &col)
{
	SNameRowColumn *pRowCol = NULL;
	size_t num = 0;
	char buf[64];
	strncpy(buf,(char*)name.ToStdString().c_str(),sizeof(buf));
	if(buf[0] == 'm' || buf[0] == 'f')
	{
		num = sizeof(NAME_ROW_COLUMN)/sizeof(NAME_ROW_COLUMN[0]);
		pRowCol = NAME_ROW_COLUMN;
	}
	else
	{
		num = sizeof(MONSTER_ROW_COLUMN)/sizeof(MONSTER_ROW_COLUMN[0]);
		pRowCol = MONSTER_ROW_COLUMN;
	}
	for(size_t i = 0; i < num; i++)
	{
		if(strstr(buf,pRowCol[i].name) != NULL)
		{
			row = pRowCol[i].r;
			col = pRowCol[i].c;
			return true;
		}
	}
	return false;
}

void ClearShadow(wxString &file)
{
	wxImage image;
	image.LoadFile(file);
	//image.ClearAlpha();
	image.SetMaskColour(0,0,0);
	image.SaveFile(file);
}

wxString GetFileName(wxString &path)
{
    wxFileName fileName(path);
    return fileName.GetName();
}

Image GetSubImage(Image &image,Geometry &rect)
{
	Color col(0,0,0,QuantumRange);
	Geometry size = image.size();
	Image subImage(size,col);
	//image.composite(subImage,rect);
	//rect.yOff(0);
	subImage.composite(image,size,OverCompositeOp);
	subImage.crop(rect);
	return subImage;
}

Image MinImage(Image &image,int w)
{
	Geometry ge = image.boundingBox();
	Geometry size = image.size();
	ge.xOff(0);
	ge.width(size.width());
	//image.crop(ge);
	Image sub = GetSubImage(image,ge);
	list<Image> imageList;
	int minX = size.width();
	int maxX = 0;
	Geometry rect;
	rect.width(size.width()/w);
	rect.height(ge.height());
	rect.yOff(ge.yOff());
	for(int i = 0; i < w; i++)
	{
		Image src(sub);
		rect.xOff(size.width()/w*i);
		//rect.yOff(0);
		src.crop(rect);
		Geometry geSub = src.boundingBox();
		if(minX > geSub.xOff())
			minX = geSub.xOff();
		if(maxX < (int)geSub.width()+geSub.xOff())
			maxX = geSub.width()+geSub.xOff();
	}
	rect.yOff(0);
	rect.height(ge.height());
	rect.width(maxX-minX);
	for(int i = 0; i < w; i++)
	{
		Image src(sub);
		rect.xOff(size.width()/w*i + minX);
		//rect.width(size.width()/w*i + maxX-rect.xOff());
		//src.crop(rect);
		imageList.push_back(GetSubImage(src,rect));
	}
	Image res;
	appendImages( &res, imageList.begin(), imageList.end()); 
	return res;
}

void SplitImage(Image &image,wxString &name,wxString &savePath,int r,int c)
{
	Geometry size = image.size();
	int w,h;
	w = size.width();
	h = size.height()/r;
	Geometry rect(w,h);
	int minx = 0,maxx = size.width();
	list<Image> imageList;
	for(size_t i = 0; i < (size_t)r; i++)
	{
		if(((r == 5) && (i == 1 || i == 2 || i == 4))
			|| (r == 2))
		{
			Image src(image);
			rect.xOff(0);
			rect.yOff(i*h);
			src.crop(rect);
			Image image = MinImage(src,c);
			imageList.push_back(image);
		}
	}
	int num = 0;
	for(list<Image>::iterator i = imageList.begin(); i != imageList.end(); i++)
	{
		i->write(wxString::Format("%s/%s%d.png",savePath,name,num).ToStdString());
		num++;
	}
}

void SplitPng(wxArrayString &arrStr,wxString &savePath)
{
	wxString err = savePath;
	err.Append("/err.txt");
	wxFile file(err,wxFile::write);
	for(unsigned int i = 0; i < arrStr.GetCount(); i++)
	{
		try
		{
			wxString name = GetFileName(arrStr[i]);
			name.MakeLower();
			if(name.find("m_") != wxString::npos || name.find("f_") != wxString::npos || name.find("g_") != wxString::npos)
				ClearShadow(arrStr[i]);
			Image image;
			image.read(arrStr[i].ToStdString());

			size_t pos = name.find("0");
			if(pos != wxString::npos)
				name.erase(pos,1);
			int r,c;
			if(GetRowCol(name,r,c))
			{
				SplitImage(image,name,savePath,r,c);
			}
		}
		catch(Exception &error_ ) 
		{
			char buf[256];
			_snprintf(buf,sizeof(buf),"%s\n",arrStr[i].ToStdString().c_str());
			file.Write(buf,strlen(buf));
			//wxMessageBox(error_.what());
		} 
		/*list<Image> imageList; 
		for(unsigned int i = 0; i < arrStr.GetCount(); i++)
		{
			Image image;
			image.read(arrStr[i].ToStdString());
			imageList.push_back(image);
		}
		Image appended; 
		appendImages( &appended, imageList.begin(), imageList.end(),true); 
		appended.write(outFile.ToStdString()); */
	}
	
}

void SplitPng(wxArrayString &arrStr,wxString &savePath,int w,int h)
{
	try
	{
		for(unsigned int i = 0; i < arrStr.GetCount(); i++)
		{
			wxString name = GetFileName(arrStr[i]);
			name.MakeLower();
			if(name.find("m_") != wxString::npos || name.find("f_") != wxString::npos || name.find("g_") != wxString::npos)
				ClearShadow(arrStr[i]);
			Image image;
			image.read(arrStr[i].ToStdString());

			size_t pos = name.find("0");
			if(pos != wxString::npos)
				name.erase(pos,1);
			SplitImage(image,name,savePath,w,h);
		}
	}
	catch( Exception &error_ ) 
    {
		wxMessageBox(error_.what());
	} 
}